package org.desktop.web.server.util;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.desktop.web.shared.domain.entities.User;
import org.json.JSONException;
import org.json.JSONObject;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sencha.gxt.data.shared.SortInfo;
import com.sencha.gxt.data.shared.SortInfoBean;
import com.sencha.gxt.data.shared.loader.FilterConfig;
import com.sencha.gxt.data.shared.loader.FilterPagingLoadConfigBean;
import com.sencha.gxt.data.shared.loader.PagingLoadConfig;

public class RpcUtil {

	public static HttpURLConnection getUrlConnection(URL _url,
			String requestMethod) throws IOException, ProtocolException {
		return getUrlConnection(_url, requestMethod,
				new HashMap<String, String>());
	}

	/**
	 * Restituisce una connessione pronta per una chiamata REST
	 * 
	 * @param _url
	 * @param requestMethod
	 * @param headers
	 * @return
	 * @throws IOException
	 * @throws ProtocolException
	 */
	public static HttpURLConnection getRESTConnection(URL _url,
			String requestMethod, Map<String, String> headers)
			throws IOException, ProtocolException {
		headers.put("Accept", "application/json");
		return getUrlConnection(_url, requestMethod, headers);
	}

	/**
	 * Da utilizzare quando c'è un invio di dati in POST.
	 * 
	 * @param con
	 * @param data
	 * @throws Exception
	 */
	public static void sendData(HttpURLConnection con, byte[] data)
			throws Exception {
		OutputStream out = null;
		try {
			con.setRequestProperty("Content-Type", "application/octet-stream");
			out = con.getOutputStream();
			out.write(data);
			out.flush();
			out.close();
		} catch (Exception e) {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
	}

	public static HttpURLConnection getUrlConnection(URL _url,
			String requestMethod, Map<String, String> headers)
			throws IOException, ProtocolException {
		HttpURLConnection con = (HttpURLConnection) _url.openConnection();
		con.setAllowUserInteraction(true);
		con.setDoInput(true);
		con.setDoOutput(true);
		con.setRequestMethod(requestMethod);
		addHeaders(headers, con);
		return con;
	}

	public static void setToken(HttpURLConnection con,
			HttpServletRequest request) {
		String cookie = request.getHeader("Cookie");
		String[] cookiesList = StringUtils.split(cookie, ';');
		for (int i = 0; i < cookiesList.length; i++) {
			String string = cookiesList[i];
			String name = string.substring(0, string.indexOf("="));
			String value = string.substring(string.indexOf("=") + 1);
			System.out.println("-->" + name + "<--: " + "##" + value + "##");
			if (name.equals("token")) {
				con.setRequestProperty(name, value);
				break;
			}
		}
	}

	/**
	 * Restituisce il nuemro della pgina della griglia per cui caricare i dati
	 * 
	 * @param loadConfig
	 * @return
	 */
	public static int getActivePage(PagingLoadConfig loadConfig) {
		// TODO Auto-generated method stub
		int activePage = (int) Math
				.ceil((double) (loadConfig.getOffset() + loadConfig.getLimit())
						/ loadConfig.getLimit());

		return activePage;
	}

	// sulla base dell'ordinamento selezionato restituisce la parte di url da
	// accodare alla chiamata per eseguire l'ordinamento remoto
	public static StringBuilder createSortUrl(List<SortInfo> sorts) {
		StringBuilder sortUrl = new StringBuilder();
		for (int i = 0; i < sorts.size(); i++) {
			SortInfoBean sort = (SortInfoBean) sorts.get(i);
			sortUrl.append("/").append(sort.getSortField()).append("-")
					.append(sort.getSortDir());

		}
		return sortUrl;
	}

	public static String createPaginationUrl(String baseUrl,
			PagingLoadConfig loadConfig, int activePage, StringBuilder sortUrl) {
		String pagination = new StringBuilder(baseUrl).append("/")
				.append(activePage - 1).append("/")
				.append(loadConfig.getLimit()).append(sortUrl.toString())
				.toString();
		return pagination;
	}

	public static void addFilters(PagingLoadConfig loadConfig,
			HttpURLConnection con) throws JSONException {
		if (loadConfig instanceof FilterPagingLoadConfigBean) {
			FilterPagingLoadConfigBean fp = (FilterPagingLoadConfigBean) loadConfig;
			// i filtri vanno passati attraverso un oggetto json nell'header
			// "filters"
			JSONObject jsonFilters = new JSONObject();
			List<FilterConfig> filters = fp.getFilters();
			for (Iterator iterator = filters.iterator(); iterator.hasNext();) {
				FilterConfig filterConfig = (FilterConfig) iterator.next();
				System.out.println("type:" + filterConfig.getType());
				if (filterConfig.getType().equals("string")) {
					jsonFilters.put(filterConfig.getField(),
							"%" + filterConfig.getValue() + "%");
				}
				if (filterConfig.getType().equals("date")) {
					System.out.println(filterConfig.getComparison());
					JSONObject obj = null;
					try {
						obj = jsonFilters
								.getJSONObject(filterConfig.getField());
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (obj == null) {
						obj = new JSONObject();

					}
					obj.put(filterConfig.getComparison(),
							Long.parseLong(filterConfig.getValue()));
					jsonFilters.put(filterConfig.getField(), obj);
				}
			}
			if (jsonFilters.length() > 0) {
				con.setRequestProperty("filters", jsonFilters.toString());
			}
		}
	}

	public static void addHeaders(Map<String, String> headers,
			HttpURLConnection con) {
		if (headers != null) {
			Iterator<String> keys = headers.keySet().iterator();
			while (keys.hasNext()) {
				String key = (String) keys.next();
				con.setRequestProperty(key, headers.get(key));
			}
		}
	}

	/**
	 * Compone l'url completa del servizio ottenendo in ingresso url
	 * (hostname+context) e endpoint (chiamate rest vera e propria)
	 * 
	 * @param servicePath
	 * @param endpoint
	 * @return
	 */
	public static String createUrlService(String servicePath, String endpoint) {
		// TODO Auto-generated method stub

		return new StringBuilder(servicePath==null?servicePath="":servicePath).append(
				servicePath.endsWith("/") ? endpoint : new StringBuilder("/")
						.append(endpoint).toString()).toString();
	}



	public static String objectToJson(Object object) throws JsonProcessingException {
		ObjectMapper map = new ObjectMapper();
		String json = map.writeValueAsString(object);
		System.out.println(json);
		return json;
	}

}
